package com.missyoubug.easyjtest.controller;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.missyoubug.easyjtest.entity.EasyTestBeanMethodVO;
import com.missyoubug.easyjtest.entity.EasyTestBeanMsgVO;
import com.missyoubug.easyjtest.entity.EasyTestBeanParameterVO;
import com.missyoubug.easyjtest.entity.EasyTestInfoEntity;
import com.missyoubug.easyjtest.service.EasyTestService;
import com.missyoubug.easyjtest.util.Code;
import com.missyoubug.easyjtest.util.EmptyChecker;
import com.missyoubug.easyjtest.util.Message;
import com.missyoubug.easyjtest.util.Messages;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

@Controller
@RequestMapping
public class MainController {

    @Autowired
    private EasyTestService eseyTestService;
    @Autowired
    private ApplicationContext context;

    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public String test(String beanName, Model model) {
        byte beanIsExist = 0;
        String beanInfos = null;
        String errMsg = null;
        if (EmptyChecker.notEmpty(beanName)){
            Message<EasyTestBeanMsgVO> jsonObjectMessage = this.searchBean(beanName);
            System.out.println(jsonObjectMessage.getData());
            if (Messages.isSuccess(jsonObjectMessage)) {
                EasyTestBeanMsgVO data = jsonObjectMessage.getData();
                StringBuilder html = new StringBuilder();
                List<EasyTestBeanMethodVO> methods = data.getMethods();
                if (EmptyChecker.isEmpty(methods)) {


                    html.append("<p> " + beanName + " no method!</p>");

                } else {
                    methods.forEach(e -> {
                        html.append("<a href='' onclick=\"return false;\"> " + e.getMethodName() + "(");
                        List<EasyTestBeanParameterVO> parameter = e.getParameterList();
                        String parameterVal = "";
                        if (EmptyChecker.notEmpty(parameter)) {
                            for (int i = 0; i < parameter.size(); i++) {
                                EasyTestBeanParameterVO parameterVo = parameter.get(i);
                                html.append(parameterVo.getParameterType() + " " + parameterVo.getParameterName());
                                parameterVal += parameterVo.getParameterType();
                                if (i <= parameter.size() - 2) {
                                    html.append(",");
                                    parameterVal += ",";
                                }
                            }
                        }
                        html.append(") <input type=\"hidden\"  value=\"" + parameterVal + "\"> </a>");
                        html.append("<br/><br/>");
                    });
                }

                beanInfos=html.toString();
                beanIsExist= 1;
                errMsg=null;

            } else {
                model.addAttribute("beanInfos", "");
                beanIsExist= 0;
                errMsg = jsonObjectMessage.getMessage();
            }


        }

        model.addAttribute("beanIsExist", beanIsExist);
        model.addAttribute("beanInfos", beanInfos);
        model.addAttribute("beanName", beanName);
        model.addAttribute("errMsg", errMsg);
        return "/search";

    }


    @RequestMapping(value = "/easyTest", method = RequestMethod.POST)
    @ResponseBody
    public String eseyTest(EasyTestInfoEntity easyTestInfoEntity) {
        //调用
        if (EmptyChecker.isAnyOneEmpty(easyTestInfoEntity.getBeanName(),
                easyTestInfoEntity.getBeanName(),
                easyTestInfoEntity.getMethodParameter())) {
            return "Bean Name,Method Name,Method Parameter is null!Please check.";
        }
        //参数
        String methodParameter = easyTestInfoEntity.getMethodParameter();
        try {
            JSONObject jsonObject = JSONObject.parseObject(methodParameter);
            Set<String> strings = jsonObject.keySet();
        } catch (JSONException e) {
            return "Method Parameter not json type,Please check.";
        }

        try {
            Object bean = context.getBean(toLowerCaseFirstOne(easyTestInfoEntity.getBeanName()));

            Method method = bean.getClass().getDeclaredMethod(easyTestInfoEntity.getMethodName());
            Type[] t = method.getGenericParameterTypes();//获取参数泛型
            Object invoke = null;
            if (t.length == 0) {
                invoke = method.invoke(bean);
            }
            for (Type paramType : t) {
                System.out.println("#" + paramType);
                if (paramType instanceof ParameterizedType) {
                    Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();
                    for (Type genericType : genericTypes) {
                        System.out.println("泛型类型" + genericType);
                    }
                }
            }

            eseyTestService.addTestInfo(easyTestInfoEntity);

            return JSONObject.toJSONString(invoke);
        } catch (Exception e) {
            return e.getMessage();
        }
    }

    /**
     * 首字母转小写
     *
     * @param s
     * @return
     */
    public String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }

    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("com.missyoubug.easyjtest.controller.TestController");
            //获取本类的所有方法，存放入数组
            Method[] methods = clazz.getDeclaredMethods();
            for (Method method : methods) {
                System.out.println("方法名：" + method.getName());
                //获取本方法所有参数类型，存入数组
                Parameter[] parameters = method.getParameters();
                if (parameters.length == 0) {
                    System.out.println("此方法无参数");
                }
                for (Parameter parameter : parameters) {
                    String name = parameter.getName();
                    Class<?> type = parameter.getType();

                    String parameterName = type.getName();
                    System.out.println("参数名：" + name + ",参数类型：" + parameterName);
                }
                System.out.println("****************************");

            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }

    @PostMapping("/search")
    @ResponseBody
    public Message<EasyTestBeanMsgVO> searchBean(String beanName) {
        Object bean;
        try {
            bean = context.getBean(toLowerCaseFirstOne(beanName));
        } catch (org.springframework.beans.factory.NoSuchBeanDefinitionException e) {
            return Messages.failed(Code.NOT_DEFINED.getValue(), "Not find java bean name is " + beanName + " in spring container!Please check!");
        }
        EasyTestBeanMsgVO beanInfos = new EasyTestBeanMsgVO();
        Method[] methods = bean.getClass().getDeclaredMethods();
        List<EasyTestBeanMethodVO> methodVOList = new ArrayList<EasyTestBeanMethodVO>(10);
        for (Method method : methods) {
            EasyTestBeanMethodVO methodVO = new EasyTestBeanMethodVO();
            System.out.println("方法名：" + method.getName());
            methodVO.setMethodName(method.getName());
            Parameter[] parameters = method.getParameters();
            if (parameters.length == 0) {
                System.out.println("此方法无参数");
            }
            List<EasyTestBeanParameterVO> params = new LinkedList<>();
            for (Parameter parameter : parameters) {
                String name = parameter.getName();
                Class<?> type = parameter.getType();
                String parameterTypeName = type.getName();
                EasyTestBeanParameterVO beanParameter = new EasyTestBeanParameterVO();
                beanParameter.setParameterName(name);
                beanParameter.setParameterType(parameterTypeName);
                params.add(beanParameter);
                System.out.println("参数名：" + name + ",参数类型：" + parameterTypeName);
            }
            methodVO.setParameterList(params);
            methodVOList.add(methodVO);
        }
        beanInfos.setBeanName(beanName);
        beanInfos.setMethods(methodVOList);
        return Messages.success(beanInfos);
    }

    @PostMapping("/middleman")
    public String middleman(EasyTestBeanMethodVO beanInfo){

        return "forword:/test.ftl";
    }
}


